//
// DbServer.cpp
// ~~~~~~~~~~~~~~
//
//

//See "5.8. Using an SSQLS in Multiple Modules" in doc/html/userman/ssqls.html. If missing this macro,
//Will occur during link: "multiple definition of `favorite::names'"
#define MYSQLPP_SSQLS_NO_STATICS
#include "favorite.h"

#include "DbServer.h"

DbServer::DbServer ()
{
    pMsgCenter = new InOutMsgCenter("BCP-Server2DB", "BCP-DB2Server") ;
    pDb = new DbService() ;
}

DbServer::~DbServer ()
{
    if (pMsgCenter)
    {
        delete pMsgCenter ;
        pMsgCenter = NULL ;
    }
    
    if (pDb)
    {
        delete pDb ;
        pDb = NULL ;
    }
}

void DbServer::run ()
{
    RecvdMsg  inMsg ;
    while (true)
    {
        pMsgCenter->startRxMsg(inMsg) ;
        processRequest( inMsg ) ;
    }
}

void DbServer::processRequest( RecvdMsg  & inMsg )
{
    Message msg = inMsg.msg ;
    msg.decode_header() ;
    LOGCON.infoStream() << msg ;

    stock::Favorite favStock ;

    if ( (favStock.ParseFromArray(msg.body(),msg.body_length())) == false)
        return ;
    if ( favStock.has_type() == false )
        return ;
    
    switch (favStock.type())
    {
    case stock::Favorite::UNUSED:
        break;
    case stock::Favorite::QUERY:
        processQueryReq(favStock) ;
        break;
    case stock::Favorite::INSERT:
        break;
    case stock::Favorite::UPDATE:
        break;
    case stock::Favorite::DELETE:
        break;
    default:
        return ;
    } ;
}
void showFav ( stock::Favorite &fav )
{
	LOGCON.infoStream()<< "Show stock::Favorite: begin\n" ;
	LOGCON.infoStream()<< "name:"        << fav.name()          << "\n" ;
	LOGCON.infoStream()<< "marketType:"  << fav.market().type() << "\n" ;
	LOGCON.infoStream()<< "type:"        << fav.type()          << "\n" ;
	LOGCON.infoStream()<< "code:"        << fav.code()          << "\n" ;
	LOGCON.infoStream()<< "price:"       << fav.price()         << "\n" ;
	LOGCON.infoStream()<< "description:" << fav.description()   << "\n" ;

	LOGCON.infoStream()<< "Show stock::Favorite: end\n" ;

}

void DbServer::processQueryReq(stock::Favorite & favStock)
{
    std::string querySQL = "select * from favorite where name='";
    querySQL += favStock.name();
    querySQL +="'";
    std::vector<favorite> res ;
    if ( pDb->query(querySQL, res) == false)
        return ;

    std::vector<favorite>::iterator it;
    for (it = res.begin(); it != res.end(); ++it)
    {
        stock::Favorite favReply ;
        Message outReply ;
		
        favReply.set_name(it->name) ;
		
        stock::Market * pMarket = favReply.mutable_market() ;
        pMarket->set_type( toStockMarketType(it->market) ) ;
		
        favReply.set_code(it->code) ;
        favReply.set_price(it->price) ;

        if (it->description != mysqlpp::null)
        {
            //You can refer the definition of class Null in file mysql++3.0.9/lib/null.h.
            favReply.set_description(it->description.data) ;
        }

		showFav(favReply) ;

        if ( favReply.ByteSize() > Message::MAX_BODY_LEN )
            continue ;
        if (!favReply.SerializeToArray((void *)(outReply.body()), (int)(Message::MAX_BODY_LEN) ))
        {
            LOGCON.errorStream() << "Failed to serialize." << "\n" ;
            continue ;
        }
        outReply.body_length(favReply.ByteSize()) ;
        outReply.encode_header() ;
        pMsgCenter->sendReply(outReply) ;
    }
}

stock::Market::MarketType DbServer::toStockMarketType ( std::string & strType ) 
	{
	LOGCON.debugStream() << "DbServer::toStockMarketType\n" << "strType=" << strType << "\n" ;
	
    stock::Market::MarketType marketType ;
    
    if (stock::Market::MarketType_Parse(strType, &marketType) == true)
        return marketType ;
    
    marketType = stock::Market::UNUSED ;
    
    return marketType ;
}



